﻿#include "MeasureView/MeasureDataSet.h"
#include "MeasureView/MeasureLine.h"
#include "MeasureView/MeasurePolyline.h"
#include "MeasureView/MeasurePolygon.h"
#include "MeasureView/MeasureCircle3P.h"
#include "MeasureView/MeasureCircle2P.h"
#include "MeasureView/MeasureCircleCenter.h"
#include "MeasureView/MeasureCircle2Circle.h"
#include "MeasureView/MeasureAngle.h"
#include "MeasureView/MeasureArc3P.h"
#include "MeasureView/MeasureDots2Line.h"
#include "MeasureView/MeasureRect.h"
#include "MeasureView/MeasureView.h"
#include "MeasureView/MeasureCount.h"
#include "MeasureView/MeasureParallelLine.h"
#include "MeasureView/MeasureCircleCenterSA.h"
#include "MeasureView/MeasureCircle2PSA.h"
#include "MeasureView/MeasureLineWidthSA.h"

#include "MeasureView/DialogMeasure.h"
#include <QDebug>
namespace Qly {
MeasureDataSet::MeasureDataSet(MeasureView *view)
{
    m_pView = view;
    m_pen = QPen(QBrush(Qt::red), 1, Qt::SolidLine);
    m_font = QFont(u8"Tahoma", 14, QFont::Bold);
}

void MeasureDataSet::showMeasureDialog()
{
    if(m_pDialogMeasure == nullptr)
    {
        m_pDialogMeasure = new DialogMeasure(this, m_pView);
    }
    if( m_pDialogMeasure )
    {
        m_pDialogMeasure->show();
    }
}

void MeasureDataSet::loadSettings(QSettings &settings)
{
    m_textTemplate_MeasureLine = settings.value("TextTemplate/MeasureLine", u8"L[@id]:@length_um @unit").toString();
    m_textTemplate_MeasureParalleLine = settings.value("TextTemplate/MeasureParallelLine", u8"L[@id]:@length_mm @unit").toString();
    m_textTemplate_MeasurePolyline = settings.value("TextTemplate/MeasurePolyline", u8"L[@id]:@length @unit").toString();
    m_textTemplate_MeasurePolygon = settings.value("TextTemplate/MeasurePolygon", u8"A[@id]:@area @areaUnit").toString();

    m_textTemplate_MeasureCircleCenter = settings.value("TextTemplate/MeasureCircleCenter", u8"R[@id]:@radius @unit").toString();
    m_textTemplate_MeasureCircle3P = settings.value("TextTemplate/MeasureCircle3P", u8"S[@id]:@area @areaUnit").toString();
    m_textTemplate_MeasureCircle2P = settings.value("TextTemplate/MeasureCircle2P", u8"D[@id]:@diameter @unit").toString();

    m_textTemplate_MeasureArc3P = settings.value("TextTemplate/MeasureArc3P", u8"[@id]:@angleDeg°, @arcLength @unit").toString();
    m_textTemplate_MeasureAngle3P = settings.value("TextTemplate/MeasureAngle3P", u8"[@id]:@angleDeg°").toString();
    m_textTemplate_MeasureAngle4P = settings.value("TextTemplate/MeasureAngle4P", u8"[@id]:@angleDeg°").toString();

    m_textTemplate_MeasureCircle2Circle = settings.value("TextTemplate/MeasureCircle2Circle", u8"[@id]:@length @unit").toString();
    m_textTemplate_MeasureDot2Line = settings.value("TextTemplate/MeasureDots2Line", u8"[@id]:@length_mm @unit").toString();
    m_textTemplate_MeasureRect = settings.value("TextTemplate/MeasureRect", u8"[@id]:@area @areaUnit").toString();
    m_textTemplate_MeasureCount = settings.value("TextTemplate/MeasureCount", u8"[@id]:").toString();

    int precision_MeasureLine = settings.value("MeasurePrecision/MeasureLine", 2).toInt();
    int precision_MeasureParallelLine = settings.value("MeasurePrecision/MeasureParallelLine", 2).toInt();
    int precision_MeasurePolyLine = settings.value("MeasurePrecision/MeasurePolyLine", 2).toInt();
    int precision_MeasurePolygon = settings.value("MeasurePrecision/MeasurePolygon", 2).toInt();

    int precision_MeasureCircleCenter = settings.value("MeasurePrecision/MeasureCircleCenter", 3).toInt();
    int precision_MeasureCircle3P = settings.value("MeasurePrecision/MeasureCircle3P", 3).toInt();
    int precision_MeasureCircle2P = settings.value("MeasurePrecision/MeasureCircle2P", 3).toInt();

    int precision_MeasureArc3P = settings.value("MeasurePrecision/MeasureArc3P", 3).toInt();
    int precision_MeasureAngle3P = settings.value("MeasurePrecision/MeasureAngle3P", 1).toInt();
    int precision_MeasureAngle4P = settings.value("MeasurePrecision/MeasureAngle4P", 2).toInt();

    int precision_MeasureCircle2Circle = settings.value("MeasurePrecision/MeasureCircle2Circle", 1).toInt();
    int precision_MeasureDot2Line = settings.value("MeasurePrecision/MeasureDot2Line", 2).toInt();
    int precision_MeasureRect = settings.value("MeasurePrecision/MeasureRect", 1).toInt();

    int precision_MeasureLineWidthSA = settings.value("MeasurePrecision/MeasureLineWidthSA", 1).toInt();

    m_unitConvert_MeasureLine.setPrecision(precision_MeasureLine);
    m_unitConvert_MeasureParallelLine.setPrecision(precision_MeasureParallelLine);
    m_unitConvert_MeasurePolyLine.setPrecision(precision_MeasurePolyLine);
    m_unitConvert_MeasurePolygon.setPrecision(precision_MeasurePolygon);

    m_unitConvert_MeasureCircleCenter.setPrecision(precision_MeasureCircleCenter);
    m_unitConvert_MeasureCircle3P.setPrecision(precision_MeasureCircle3P);
    m_unitConvert_MeasureCircle2P.setPrecision(precision_MeasureCircle2P);

    m_unitConvert_MeasureArc3P.setPrecision(precision_MeasureArc3P);
    m_unitConvert_MeasureAngle3P.setPrecision(precision_MeasureAngle3P);
    m_unitConvert_MeasureAngle4P.setPrecision(precision_MeasureAngle4P);

    m_unitConvert_MeasureCircle2Circle.setPrecision(precision_MeasureCircle2Circle);
    m_unitConvert_MeasureDot2Line.setPrecision(precision_MeasureDot2Line);
    m_unitConvert_MeasureRect.setPrecision(precision_MeasureRect);

    m_unitConvert_MeasureLineWidthSA.setPrecision(precision_MeasureLineWidthSA);
}

void MeasureDataSet::writeSettings(QSettings &settings)
{
    settings.setValue("TextTemplate/MeasureLine",  m_textTemplate_MeasureLine);
    settings.setValue("TextTemplate/MeasureParallelLine", m_textTemplate_MeasureParalleLine);
    settings.setValue("TextTemplate/MeasurePolyline", m_textTemplate_MeasurePolyline);
    settings.setValue("TextTemplate/MeasurePolygon", m_textTemplate_MeasurePolygon);

    settings.setValue("TextTemplate/MeasureCircleCenter", m_textTemplate_MeasureCircleCenter);
    settings.setValue("TextTemplate/MeasureCircle3P", m_textTemplate_MeasureCircle3P);
    settings.setValue("TextTemplate/MeasureCircle2P", m_textTemplate_MeasureCircle2P);

    settings.setValue("TextTemplate/MeasureArc3P", m_textTemplate_MeasureArc3P);
    settings.setValue("TextTemplate/MeasureAngle3P", m_textTemplate_MeasureAngle3P);
    settings.setValue("TextTemplate/MeasureAngle4P", m_textTemplate_MeasureAngle4P);

    settings.setValue("TextTemplate/MeasureCircle2Circle", m_textTemplate_MeasureCircle2Circle);
    settings.setValue("TextTemplate/MeasureDots2Line", m_textTemplate_MeasureDot2Line);
    settings.setValue("TextTemplate/MeasureRect", m_textTemplate_MeasureRect);
    settings.setValue("TextTemplate/MeasureCount", m_textTemplate_MeasureCount);

    settings.setValue("MeasurePrecision/MeasureLine", m_unitConvert_MeasureLine.precision());
    settings.setValue("MeasurePrecision/MeasureParallelLine", m_unitConvert_MeasureParallelLine.precision());
    settings.setValue("MeasurePrecision/MeasurePolyLine", m_unitConvert_MeasurePolyLine.precision());
    settings.setValue("MeasurePrecision/MeasurePolygon", m_unitConvert_MeasurePolygon.precision());

    settings.setValue("MeasurePrecision/MeasureCircleCenter", m_unitConvert_MeasureCircleCenter.precision());
    settings.setValue("MeasurePrecision/MeasureCircle3P", m_unitConvert_MeasureCircle3P.precision());
    settings.setValue("MeasurePrecision/MeasureCircle2P", m_unitConvert_MeasureCircle2P.precision());

    settings.setValue("MeasurePrecision/MeasureArc3P", m_unitConvert_MeasureArc3P.precision());
    settings.setValue("MeasurePrecision/MeasureAngle3P", m_unitConvert_MeasureAngle3P.precision());
    settings.setValue("MeasurePrecision/MeasureAngle4P", m_unitConvert_MeasureAngle4P.precision());

    settings.setValue("MeasurePrecision/MeasureCircle2Circle", m_unitConvert_MeasureCircle2Circle.precision());
    settings.setValue("MeasurePrecision/MeasureDot2Line", m_unitConvert_MeasureDot2Line.precision());
    settings.setValue("MeasurePrecision/MeasureRect", m_unitConvert_MeasureRect.precision());

    settings.setValue("MeasurePrecision/MeasureLineWidthSA", m_unitConvert_MeasureLineWidthSA.precision());

}

void MeasureDataSet::setPixelSize(double newPixelSize_um, int method)
{
    m_pixSize_um = newPixelSize_um;
    if( !m_pCurrentElement )
    {
        delete m_pCurrentElement;
        m_pCurrentElement = nullptr;
    }
    QListIterator<MeasureElement *> iter(m_elementList);
    for(;iter.hasNext();)
    {
        MeasureElement * pElement = iter.next();
        pElement->setPixelSize(newPixelSize_um, method);
    }
}

void MeasureDataSet::paint(QPainter &painter, int image_width, int image_height)
{
    Q_UNUSED(image_width);
    Q_UNUSED(image_height);
    QListIterator<MeasureElement *> iter(m_elementList);
    for(;iter.hasNext();)
    {
        MeasureElement * pElement = iter.next();
        pElement->paint(painter);
    }
}


void MeasureDataSet::clearAll()
{
    while( !m_elementList.isEmpty() )
    {
        MeasureElement *p = m_elementList.takeLast();
        m_pCurrentElement = nullptr;
        delete p;
    }
    reset_id();
    if(m_pView)
    {
        m_pView->update();
    }
}

void MeasureDataSet::undo()
{
    if( !m_elementList.isEmpty() )
    {
        MeasureElement *p = m_elementList.takeLast();
        m_pCurrentElement = nullptr;
        delete p;
        if(m_pView)
        {
            m_pView->update();
        }
    }
}

void MeasureDataSet::updateText()
{
    QListIterator<MeasureElement *> iter(m_elementList);
    for(;iter.hasNext();)
    {
        MeasureElement * pElement = iter.next();
        //pElement->setTemplate()
        pElement->updateText(true);
    }
}

bool MeasureDataSet::deleteElement(MeasureElement *element)
{
    bool updateID = false;
    QList<MeasureElement *>::iterator iter;
    //TODO 先要找到这个元素，然后删除
    for (iter = m_elementList.begin(); iter != m_elementList.end(); ++iter)
    {
        if((*iter) == element)
        {
            break;
        }
    }
    if( iter == m_elementList.end() ) //没找到这个元素，直接返回
    {
        return false;
    }
    m_elementList.erase(iter);
    reset_id();
    //MeasureElement::s_id = 0;
    for (iter = m_elementList.begin(); iter != m_elementList.end(); ++iter)
    {
        m_element_id ++;
        //MeasureElement::s_id ++;
        (*iter)->setID(m_element_id);
        if((*iter)->type() == MeasureElement::Dots2Line)
        {

        }
        (*iter)->updateText();
    }
//    emit elementDeleted(*iter);
    return true; //  删了一个就退出。保证每次最多就删一个
}


//void MeasureDataSet::setLens(int oldLensIndex, int newLensIndex, int method)
//{
//    if( !m_pCurrentElement )
//    {
//        delete m_pCurrentElement;
//        m_pCurrentElement = nullptr;
//    }
//    QListIterator<MeasureElement *> iter(m_elementList);
//    for(;iter.hasNext();)
//    {
//        MeasureElement * pElement = iter.next();
//        pElement->setLens(oldLensIndex, newLensIndex, method);
//    }
//}

MeasureElement *MeasureDataSet::findElement(const QPointF &pt)
{
    qDebug() << "in MeasureDataSet::findElement";
    MeasureElement *pShape = nullptr;
    QList<MeasureElement *>::iterator iter;
    for (iter = m_elementList.begin(); iter != m_elementList.end(); ++iter)
    {
        qDebug() << "type() = " << (*iter)->type();
        if((*iter)->type() == MeasureElement::Line)
        {
            MeasureLine *l = (MeasureLine*) *iter;
            if(l->testMoveState(pt))
            {
                pShape = l;
                break;
            }
        }
        if( (*iter)->isInTextBox(pt) )
        {
            pShape = *iter;
            break;
        }
    }
    return pShape;
}

MeasureElement *MeasureDataSet::deleteElement(QPointF p)
{
    bool updateID = false;
    QList<MeasureElement *>::iterator iter;

    for (iter = m_elementList.begin(); iter != m_elementList.end(); ++iter)
    {
        switch ((*iter)->tryDelete(p))
        {
        case MeasureElement::DeleteByMyself:
//            updateID = true;
//            MeasureElement::s_id = 0;
//            for (iter = m_elementList.begin(); iter != m_elementList.end(); ++iter)
//            {
//                MeasureElement::s_id ++;
//                (*iter)->setID(MeasureElement::s_id);
//                if((*iter)->type() == MeasureElement::Dots2Line)
//                {

//                }
//                (*iter)->updateText();
//            }
            emit elementUpdated(*iter);
            return nullptr;
        case MeasureElement::DeleteByOther:
//            updateID = true;
            m_elementList.erase(iter);
            reset_id();
            //MeasureElement::s_id = 0;
            for (iter = m_elementList.begin(); iter != m_elementList.end(); ++iter)
            {
                m_element_id ++;
                //MeasureElement::s_id ++;
                (*iter)->setID(m_element_id);
                if((*iter)->type() == MeasureElement::Dots2Line)
                {

                }
                (*iter)->updateText();
            }
            emit elementDeleted(*iter);
            return *iter; //  删了一个就退出。保证每次最多就删一个
        case MeasureElement::DeleteNothing:
            break;
        }
    }
    if(updateID)
    {

    }
    return nullptr; //到这里说明什么都没删除
}

int MeasureDataSet::mouseLButtonPress(QPointF point_pix, QPointF point_um)
{
//    qDebug() << "m_elementType = " << m_elementType;
    if( m_elementType == MeasureElement::None )
    {
        m_pElementFind = findElement(point_pix);
        //qDebug() << "m_pElementFind = " << m_pElementFind;
        return (m_pElementFind != 0);
    }

    if( m_elementType == MeasureElement::Delete )
    {
        deleteElement(point_pix);
        return 1;
    }
    if( m_pCurrentElement != nullptr && m_pCurrentElement->state() != MeasureElement::DS_FINISH )
    {
        m_pCurrentElement->mouseLButtonPress(point_pix, point_um); //
        if( m_pCurrentElement->state() == MeasureElement::DS_FINISH ) //表明当前图形已经完全确定
        {
            emit elementAdded(m_pCurrentElement);
            m_pCurrentElement = nullptr;
            m_pView->update();
        }
        return 2;
    }
    if( !m_pCurrentElement )//如果当前没有正在测量的元素，则应该新建一个
    {
        switch (m_elementType)
        {
        case MeasureElement::Line:
            m_pCurrentElement = new MeasureLine(this);
            break;
        case MeasureElement::Polyline:
            m_pCurrentElement = new MeasurePolyline(this);
            break;
        case MeasureElement::Polygon:
            m_pCurrentElement = new MeasurePolygon(this);
            break;
        case MeasureElement::Circle3P:
            m_pCurrentElement = new MeasureCircle3P(this);
            break;
        case MeasureElement::Circle2P:
            m_pCurrentElement = new MeasureCircle2P(this);
            break;
        case MeasureElement::CircleCenter:
            m_pCurrentElement = new MeasureCircleCenter(this);
            break;
        case MeasureElement::LineWidth_SA:
            m_pCurrentElement = new MeasureLineWidthSA(this);
            break;
        case MeasureElement::Circle2P_SA:
            m_pCurrentElement = new MeasureCircle2PSA(this);
            break;
        case MeasureElement::CircleCenter_SA:
            m_pCurrentElement = new MeasureCircleCenterSA(this);
            break;
        case MeasureElement::Angle3P:
            m_pCurrentElement = new MeasureAngle3P(this);
            break;
        case MeasureElement::Angle4P:
            m_pCurrentElement = new MeasureAngle4P(this);
            break;
        case MeasureElement::Circle2Circle:
            m_pCurrentElement = new MeasureCircle2Circle(this);
            break;
        case MeasureElement::Arc3P:
            m_pCurrentElement = new MeasureArc3P(this);
            break;
        case MeasureElement::Dots2Line:
            m_pCurrentElement = new MeasureDots2Line(this);
            break;
        case MeasureElement::ParallelLine:
            m_pCurrentElement = new MeasureParallelLine(this);
            break;
        case MeasureElement::Rect:
            m_pCurrentElement = new MeasureRect(this);
            break;
        case MeasureElement::Count:
            m_pCurrentElement = new MeasureCount(this);
            break;
        default:
            return 0;
        }
        if(m_pCurrentElement)
        {
            qDebug() << u8"新建了测量元素，类型为：" << m_pCurrentElement->type() << u8", 地址为：" << m_pCurrentElement;
            m_pCurrentElement->setPen(m_pen);
            m_pCurrentElement->setFont(m_font);
            m_pCurrentElement->mouseLButtonPress(point_pix, point_um);
            m_elementList << m_pCurrentElement;
            return 1;
        }
        return 0;
    }
    return 0;
}

int MeasureDataSet::mouseRButtonPress(QPointF point_pix, QPointF point_um)
{
    if( m_pCurrentElement != nullptr && m_pCurrentElement->state() != MeasureElement::DS_FINISH )
    {
        m_pCurrentElement->mouseRButtonPress(point_pix, point_um);
        if( m_pCurrentElement->state() == MeasureElement::DS_FINISH ) //表明当前图形已经完全确定
        {
            emit elementAdded(m_pCurrentElement);
            m_pCurrentElement = nullptr;
        }
        return 1;
    }
    return 0;
}

int MeasureDataSet::mouseMove(QPointF point_pix, QPointF point_um)
{
    if( m_elementType == MeasureElement::None && m_pElementFind != nullptr )
    {
        QPointF offset_pix = point_pix - m_startPoint_pix;
        QPointF offset_um = point_um - m_startPoint_um;
        if(m_pElementFind ->type() == MeasureElement::Line)
        {
            MeasureLine * l = (MeasureLine * )m_pElementFind;
            if(l->adjust(offset_pix, offset_um))
            {
                m_startPoint_pix = point_pix;
                m_startPoint_um = point_um;
                return 1;
            }
        }
        m_pElementFind->textMove(offset_pix, offset_um);
        m_startPoint_pix = point_pix;
        m_startPoint_um = point_um;
        return 1;
    }
    if( m_pCurrentElement == nullptr )
    {
        return 0;
    }
    return m_pCurrentElement->mouseMove(point_pix, point_um);
}

int MeasureDataSet::mouseRelease(QPointF point_pix, QPointF point_um)
{
    if( m_pElementFind )// 说明刚在在拖动图元
    {
        if(m_pElementFind ->type() == MeasureElement::Line)
        {
            MeasureLine * l = (MeasureLine * )m_pElementFind;
            l->cancelMoveState();
        }
        if(m_pElementFind->mouseLButtonRelease(point_pix, point_um))
        {
            m_pView->update();
        }
    }
    m_pElementFind = nullptr;
    if( m_elementType != MeasureElement::None  && m_pCurrentElement != nullptr )
    {
        int ret = m_pCurrentElement->mouseLButtonRelease(point_pix, point_um);
        if( m_pCurrentElement->state() == MeasureElement::DS_ERROR )
        {
            MeasureElement *p = m_elementList.takeLast();
            delete p;
            m_pCurrentElement = nullptr;
        }

        else if( m_pCurrentElement->state() == MeasureElement::DS_FINISH ) //表明当前图形已经完全确定
        {
            m_pCurrentElement = nullptr;
        }
        if(ret)
        {
            m_pView->update();
        }
    }
    return 1;
}

QList<MeasureElement *> MeasureDataSet::elementList()
{
    return m_elementList;
}

int MeasureDataSet::setElementType(MeasureElement::ElementType type)
{
    qDebug () << u8"更改测量类型为：" << type ;
    if(type == m_elementType)
    {
        return 0; // 没有改变，直接返回
    }
    if( !m_pCurrentElement )
    {
        qDebug() << u8", 当前测量元素 m_pCurrentElement 为空。";
        if(type == MeasureElement::Dots2Line && m_elementType == MeasureElement::Delete && !m_elementList.isEmpty())
        {  
            MeasureElement *p = m_elementList.last();
            qDebug() << u8"当前是点到线测量，之前是删除。" << u8"上一个测量元素是：" << p->type() << u8", 地址为：" << p;
            if( p->type() == MeasureElement::Dots2Line ) //这时应该恢复点到线测量
            {
                qDebug() << u8"这时应该恢复点到线测量。";
                m_pCurrentElement = p;
                MeasureDots2Line * pp = (MeasureDots2Line*) p;
                pp->resume();
            }
        }
        m_elementType = type;
        return 0;
    }

    if(m_pCurrentElement->type() == MeasureElement::Count || m_pCurrentElement->type() == MeasureElement::Dots2Line)
    {
        qDebug() << u8"更改测量类型为：" << type << u8"，之前的测量类型为：" << m_pCurrentElement->type();
        qDebug() << u8"这时应该先关闭之前的测量。";
        m_pCurrentElement->finish();
        m_pCurrentElement = nullptr;
        m_elementType = type;
        m_pView->update();
        return 2;
    }
    qDebug() << u8", 当前测量元素 m_pCurrentElement == " << m_pCurrentElement << u8"应该将当前测量元素删除。";
    MeasureElement *p = m_elementList.takeLast();
    if(p != m_pCurrentElement)
    {
        qWarning() << u8"Error: m_pCurrentElement must point to m_elementList.last()";
    }

    delete p;
    m_pCurrentElement = nullptr;

    m_elementType = type;
    m_pView->update();
    return 1;
}
}
